package test;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.apache.commons.lang3.StringUtils;

/**
* @author 作者 linweiqiang
* @version 创建时间：2017年11月14日 上午9:29:09
* 类说明
*/
public class MyUrlRequest {
	
	public static String httpRequestString(String requestUrl,String method,Map<String,String> map){
		StringBuilder buffer = new StringBuilder();
		InputStream is = null;
		InputStreamReader isr = null;
		try {
			is = ByteTFInputStream.byte2Input(httpRequest(requestUrl, method, map , false , false));
			isr = new InputStreamReader(is,"utf-8");
	        BufferedReader br=new BufferedReader(isr);  
	        String line=null;  
	        while((line=br.readLine())!=null){  
	            buffer.append(line);  
	        }  
	        isr.close();
	        is.close();
		} catch ( IOException e) {
			e.printStackTrace();
		}finally {
			if(isr!=null){
				try {
					isr.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			if(is!=null){
				try {
					is.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		return buffer.toString();
	}
	
	/**
	 * url post 请求
	 * @param requestUrl 请求url
	 * @param map 请求参数
	 * @return
	 */
	public static byte[] httpRequest(String requestUrl , String method,Map<String,String> map ,boolean userAgent ,boolean referer){
		InputStream is = null;
		HttpURLConnection conn = null;
		byte [] result = null;
		try {
			URL url = new URL(requestUrl);
			conn = (HttpURLConnection) url.openConnection();
			//设置是否向conn输出，因为这是个post请求，参数要放在http正文内，因此要设为true
			conn.setDoOutput(true);
			//从conn中读取默认为true
			conn.setDoInput(true);
			//设置请求为post（默认为get）
			conn.setRequestMethod(method);
			//post请求不能试用缓存
			conn.setUseCaches(false);
			//设置本次连接是否自动处理重定向，设置为true，系统自动处理重定向，设置成false，则需要自己从http reply 中分析新的url自己重新连接
			conn.setInstanceFollowRedirects(true);
			//配置本次连接的conten-type，配置为application/x-www-form-urlencoded（意思是正文是URL恩code的编码过的form参数），下面需要我们对正文内容试用URLEncoder.encode进行编码
			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			//设置超时 
			conn.setConnectTimeout(1000 * 60 * 3);
			//伪装浏览器
			if(userAgent){
				conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
			}
			//伪装路由
			if(referer){
				String refStr = url.getProtocol()+"://"+url.getHost();
				conn.setRequestProperty("Referer", refStr);
			}
			conn.connect();
			if(map!=null){
				String params = map2String(map);
				if(!StringUtils.isBlank(params)){
					DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
					dos.writeBytes(params);
					dos.flush();
					dos.close();
				}
			}
	        is = conn.getInputStream();
	        result = ByteTFInputStream.input2Byte(is);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(conn != null){
				conn.disconnect();
			}
		}
		return result;
	}
	
	public static String httpsRequestString(String requestUrl, String method, Map<String,String> map){
		StringBuilder buffer = new StringBuilder();
		InputStream is = null;
		InputStreamReader isr = null;
		try {
			is = ByteTFInputStream.byte2Input(httpsRequest(requestUrl, method, map,false,false));
			isr = new InputStreamReader(is,"utf-8");
	        BufferedReader br=new BufferedReader(isr);  
	        String line=null;  
	        while((line=br.readLine())!=null){  
	            buffer.append(line);  
	        }  
	        isr.close();
	        is.close();
		} catch ( IOException e) {
			e.printStackTrace();
		}finally {
			if(isr!=null){
				try {
					isr.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
			if(is!=null){
				try {
					is.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		}
		return buffer.toString();
	}
	
	
	/**
	 * https请求
	 * https对连接加了安全证书ssl的，如果服务器没有相关连接的ssl证书，他就不能够信任那个连接，
	 * 也就不会访问到。所有要自定义一个信任管理器，实现自带的X509TrustManager接口就可以了。
	 * @param requestUrl  请求url
	 * @param method 请求方法  GET 或 POST
	 * @param map 请求参数
	 * @return
	 */
	public static byte[] httpsRequest(String requestUrl, String method, Map<String,String> map ,boolean userAgent ,boolean referer){
		InputStream is = null;
		HttpsURLConnection conn = null;
		byte[] result = null;
		try {
			//创建SSLContext
			SSLContext sslContext = SSLContext.getInstance("SSL");
			TrustManager[] tm = {new MyX509TrustManager()};
			//初始化
			sslContext.init(null, tm, new java.security.SecureRandom());
			//获取SSLSocketFactory
			SSLSocketFactory ssf = sslContext.getSocketFactory();
			URL url = new URL(requestUrl);
			conn = (HttpsURLConnection) url.openConnection();
			//设置当前实例使用的SSLSocketFactory
			conn.setSSLSocketFactory(ssf);
			//设置是否向conn输出，因为这是个post请求，参数要放在http正文内，因此要设为true
			conn.setDoOutput(true);
			//从conn中读取默认为true
			conn.setDoInput(true);
			//设置请求为post（默认为get）
			conn.setRequestMethod(method);
			//post请求不能试用缓存
			conn.setUseCaches(false);
			//设置本次连接是否自动处理重定向，设置为true，系统自动处理重定向，设置成false，则需要自己从http reply 中分析新的url自己重新连接
			conn.setInstanceFollowRedirects(true);
			//配置本次连接的conten-type，配置为application/x-www-form-urlencoded（意思是正文是URL恩code的编码过的form参数），下面需要我们对正文内容试用URLEncoder.encode进行编码
			conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			//伪装浏览器
			if(userAgent){
				conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
			}
			//伪装路由
			if(referer){
				String refStr = url.getProtocol()+"://"+url.getHost();
				conn.setRequestProperty("Referer", refStr);
			}
			conn.connect();
			String params = map2String(map);
			if(!StringUtils.isBlank(params)){
				DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
				dos.writeBytes(params);
				dos.flush();
				dos.close();
			}
			 //读取服务器端返回的内容  
			StringBuilder buffer = new StringBuilder();
	        is = conn.getInputStream();
	        result = ByteTFInputStream.input2Byte(is);
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(conn!=null){
				conn.disconnect();
			}
		}
		
		return result;
	}
	
	public static byte[] http403Request(String requestUrl){
		return httpRequest(requestUrl, "GET", null, true, true);
	}
	public static byte[] https403Request(String requestUrl){
		return httpsRequest(requestUrl, "GET", null, true, true);
	}
	
	
	/**
	 * 将map里面的参数转换成字符串
	 * key=val&key=val...
	 * @param map
	 * @return
	 */
	public static String map2String(Map<String,String> map){
		if(map == null)
			return null;
		StringBuilder params = new StringBuilder();
		for (String key : map.keySet()) {
			if(StringUtils.isBlank(key)||StringUtils.isBlank(map.get(key)))
				continue;
			try {
				params.append(URLEncoder.encode(key,"utf-8") + "=" + URLEncoder.encode(map.get(key), "utf-8"));
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			params.append("&");
		}
		if(!StringUtils.isBlank(params)){
			params.deleteCharAt(params.length() - 1);
			return params.toString();
		}
		return null;
	}
	
	
}
